//
//  HsSignUtil.m
//  Core
//
//  Created by pquanshan on 15/12/22.
//  Copyright © 2015年 chenhf. All rights reserved.
//

#import "HsSignUtil.h"
#import<CommonCrypto/CommonDigest.h>
#import "NSDate+Extension.h"
#import "NSDictionary+Extra.h"

@implementation HsSignUtil

+(NSMutableDictionary *)getSignParams:(NSMutableDictionary *)params secret:(NSString*)secret
{
    
    NSAssert([params isKindOfClass:[NSMutableDictionary class]], @"TTTT参数params必须为NSMutableDictionary类型");
    [params setObject:[NSDate currentStrTimestamp] forKey:@"timestamp"];
    [params setObject:secret forKey:@"secret"];
    
    [params setObject:[self HMACMD5WithString:[params sortByKeys:NO] WithKey:secret] forKey:@"sign"];
    
    return params;
}

+(NSMutableDictionary *)getSignMD5Params:(NSDictionary *)params
{
//    NSLog(@"T*签名日志*T");
    NSAssert([params isKindOfClass:[NSDictionary class]], @"T*参数params必须为NSDictionary类型");
    NSMutableDictionary *pdic=[[NSMutableDictionary alloc] initWithDictionary:[params copy]];
    
    [pdic setObject:[NSDate currentStrTimestamp] forKey:@"timestamp"];
    NSString *paramStr=[NSString stringWithFormat:@"yita0308%@yita0308",[pdic sortByKeys:NO]];
//    paramStr=[paramStr stringByReplacingOccurrencesOfString:@"&" withString:@""];
//    paramStr=[paramStr stringByReplacingOccurrencesOfString:@"=" withString:@""];
    NSString *signStr=[paramStr md5String];
//    NSLog(@"T*签名前字符串：%@\n",paramStr);
//    NSLog(@"T*签名后字符串：%@\n",signStr);
    [pdic setObject:signStr forKey:@"sign"];
//    NSLog(@"T*参与签名后的参数：%@\n",params);
//    NSLog(@"T*签名日志结束*T\n");
    return pdic;
}

+(NSString*)signForUrl:(NSString*)url postParams:(NSDictionary*)params secret:(NSString*)secret{
    NSString* signStr = [HsSignUtil getSign:url postParams:params];
    signStr = [HsSignUtil HMACMD5WithString:signStr WithKey:secret];
    return signStr;
}


+(NSString*)getSign:(NSString*)url postParams:(NSDictionary*)params{
    NSMutableArray* keyArr = [[NSMutableArray alloc] init];//参数名缓存，用于按升序进行排序
    NSMutableDictionary* keyValueDic = [[NSMutableDictionary alloc] init];//sign参数按"key=value"缓存起来作为Value，Key为参数名key
    
    NSArray* comArr = [url componentsSeparatedByString:@"?"];
    if (comArr.count == 2) {
        NSString* urlRequest = [comArr lastObject];//请求参数
        NSArray* comUrlRequestArr = [urlRequest componentsSeparatedByString:@"&"];
        for (NSString* itemKeyValue in comUrlRequestArr) {
            NSArray* ikvArr = [itemKeyValue componentsSeparatedByString:@"="];
            if (ikvArr.count == 2) {
                NSString* key = [ikvArr firstObject];
                [keyArr addObject:key]; //将要用来排序的字段缓存起来
                [keyValueDic setObject:itemKeyValue forKey:key];//将所有参数按"key=value"缓存起来
            }else{
                NSLog(@"url:%@ 生成 KSRSign 数据源格式异常参数:%@",url,itemKeyValue);
            }
        }
    }
    if (params) {//请求参数
        NSArray* dicKeyArr = [params allKeys];
        for (NSString* key in dicKeyArr) {
            [keyArr addObject:key];
            NSString* value = [params objectForKey:key];//将要用来排序的字段缓存起来
            value = [NSString stringWithFormat: @"%@=%@",key,value];//将所有参数按"key=value"缓存起来
            [keyValueDic setObject:value forKey:key];
        }
    }
    
    //先将参数以其参数名的字典序升序进行排序
    NSArray* sortedArray = [keyArr sortedArrayUsingComparator:^(NSString * obj1, NSString * obj2){
        return (NSComparisonResult)[obj1 compare:obj2 options:NSNumericSearch];
    }];
    //遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
    NSString* signStr = @"";
    for (NSString* keyStr in sortedArray) {
        if (signStr.length > 0) {
            signStr = [signStr stringByAppendingString:@"&"];
        }
        signStr = [signStr stringByAppendingString:[keyValueDic objectForKey:keyStr]];
    }
    return signStr;
}

+(NSString *)getSignUrl:(NSString *)url withParam:(NSDictionary *)params
{
    NSMutableArray* keyArr = [[NSMutableArray alloc] init];//参数名缓存，用于按升序进行排序
    NSMutableDictionary* keyValueDic = [[NSMutableDictionary alloc] init];//sign参数
    if (params) {//请求参数
        NSArray* dicKeyArr = [params allKeys];
        for (NSString* key in dicKeyArr) {
            [keyArr addObject:key];
            NSString* value = [params objectForKey:key];//将要用来排序的字段缓存起来
            value = [NSString stringWithFormat: @"%@=%@",key,value];//将所有参数按"key=value"缓存起来
            [keyValueDic setObject:value forKey:key];
        }
    }
    //遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
    NSString* signStr = @"";
    for (NSString* keyStr in keyArr) {
        if (signStr.length > 0) {
            signStr = [signStr stringByAppendingString:@"&"];
        }
        signStr = [signStr stringByAppendingString:[keyValueDic objectForKey:keyStr]];
    }
    return [NSString stringWithFormat:@"%@?%@",url,signStr];
}



+ (NSString *)md5HexDigest:(NSString *)url{
    const char *original_str = [url UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(original_str, strlen(original_str), result);
    NSMutableString *hash = [NSMutableString string];
    for (int i = 0; i < 16; i++)
        [hash appendFormat:@"%02X", result[i]];
    return [hash lowercaseString];
}

+ (NSString *)HMACMD5WithString:(NSString *)toEncryptStr WithKey:(NSString *)keyStr{
    const char *cKey  = [keyStr cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [toEncryptStr cStringUsingEncoding:NSUTF8StringEncoding];
    const unsigned int blockSize = 64;
    char ipad[blockSize];
    char opad[blockSize];
    char keypad[blockSize];
    
    unsigned int keyLen = strlen(cKey);
    CC_MD5_CTX ctxt;
    if (keyLen > blockSize) {
        CC_MD5_Init(&ctxt);
        CC_MD5_Update(&ctxt, cKey, keyLen);
        CC_MD5_Final((unsigned char *)keypad, &ctxt);
        keyLen = CC_MD5_DIGEST_LENGTH;
    }
    else {
        memcpy(keypad, cKey, keyLen);
    }
    
    memset(ipad, 0x36, blockSize);
    memset(opad, 0x5c, blockSize);
    
    int i;
    for (i = 0; i < keyLen; i++) {
        ipad[i] ^= keypad[i];
        opad[i] ^= keypad[i];
    }
    
    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, ipad, blockSize);
    CC_MD5_Update(&ctxt, cData, strlen(cData));
    unsigned char md5[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(md5, &ctxt);
    
    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, opad, blockSize);
    CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH);
    CC_MD5_Final(md5, &ctxt);
    
    const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2;
    char hex[hex_len];
    for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]);
    }
    
    NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)];
    NSString *hash = [[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding];
    return hash;
}

//比较版本的方法，在这里用Version来比较的
+ (BOOL)compareVersionsFormAppStore:(NSString*)AppStoreVersion WithAppVersion:(NSString*)AppVersion{
    
    if ([AppStoreVersion isKindOfClass:[NSNull class]]) {
        return NO;
    }
    
    BOOL littleSunResult = false;
    
    NSMutableArray* a = (NSMutableArray*) [AppStoreVersion componentsSeparatedByString: @"."];
    NSMutableArray* b = (NSMutableArray*) [AppVersion componentsSeparatedByString: @"."];
    
    while (a.count < b.count) { [a addObject: @"0"]; }
    while (b.count < a.count) { [b addObject: @"0"]; }
    
    for (int j = 0; j<a.count; j++) {
        if ([[a objectAtIndex:j] integerValue] > [[b objectAtIndex:j] integerValue]) {
            littleSunResult = true;
            break;
        }else if([[a objectAtIndex:j] integerValue] < [[b objectAtIndex:j] integerValue]){
            littleSunResult = false;
            break;
        }else{
            littleSunResult = false;
        }
    }
    return littleSunResult;//true就是有新版本，false就是没有新版本
    
}


@end
